package com.puff.jdbc.tx.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

import com.puff.framework.annotation.Transaction;
import com.puff.framework.utils.ClassUtil;
import com.puff.jdbc.core.DataBase;
import com.puff.jdbc.core.DbManager;

public class JDKProxy implements TXProxy, InvocationHandler {

	private Object target;

	public JDKProxy(Class<?> klass) {
		super();
		this.target = ClassUtil.newInstance(klass.getName());
	}

	public Object getProxy() {
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object target, Method method, Object[] args) throws Throwable {
		Object result = null;
		method.setAccessible(true);
		Transaction tran = method.getAnnotation(Transaction.class);
		if (tran != null) {
			Connection conn = DataBase.getThreadLocalConnection();
			// 嵌套事务
			if (conn != null) {
				return method.invoke(target, args);
			}
			Boolean autoCommit = null;
			try {
				conn = DbManager.getConnection(tran.value());
				autoCommit = conn.getAutoCommit();
				DataBase.setThreadLocalConnection(conn);
				conn.setAutoCommit(false);
				result = method.invoke(target, args);
				conn.commit();
			} catch (Throwable t) {
				if (conn != null)
					try {
						conn.rollback();
					} catch (Exception e) {

					}
			} finally {
				try {
					if (conn != null) {
						if (autoCommit != null)
							conn.setAutoCommit(autoCommit);
						conn.close();
					}
				} catch (Throwable t) {

				} finally {
					DataBase.removeThreadLocalConnection();
				}
			}
		} else {
			result = method.invoke(target, args);
		}
		return result;
	}

}
